package com.fingard.dsp.bank.directbank.cmb01;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.dbobj.updownfile.DownFileHelper;
import com.fingard.dsp.bank.dbobj.updownfile.DownFileRecord;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.directbank.boc01.receiptpro.BOC01TaskReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.generalobj.ExecResponse;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

public class CMB01ReceiptPro extends CMB01Base implements IReceiptPro {

	public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay)
			throws Exception {

		boolean execDownAsap = false;//提交回单下载完成后，标识下载文件任务不需延时
		//（1:未打印，2:已打印）
		String[] printFlags = new String[]{"2", "1"};
		//查回单禁用第一步SDKCSFDFBRT，数据量很大时第一步会查不回
		boolean disableReceiptFirstStep = this.getBankConfig().getValueAsBool("disableReceiptFirstStep");
		DownFileHelper dfHelper = new DownFileHelper(bankFront.tenant, pOneDay);
		for (String printFlag : printFlags) {
			try {
				String tmpDate = Format.Date8Format.format(pOneDay);
				if("2".equals(printFlag)){
					this.WriteBankLogLn("查询"+tmpDate+"（2:已打印）的回单数据");
				}else if("1".equals(printFlag)){
					this.WriteBankLogLn("查询"+tmpDate+"（1:未打印）的回单数据");
				}
				
				int qryDate = Integer.parseInt(Format.Date8Format.format(new Date()));
				String fileKey = tmpDate+"-SDKCSFDFBRTIMG-RRCFLG-"+printFlag;
				
				if(!disableReceiptFirstStep){//没有禁用
					//第一步查回单数据
					CMB01Header bnkHeader1 = new CMB01Header();
					bnkHeader1.FUNNAM = "SDKCSFDFBRT";

	                XmlTextWriter xmlWriter1 = new XmlTextWriter();
	                xmlWriter1.autoFormat = false;
	                writeCommonHeader(xmlWriter1, bnkHeader1);

	                xmlWriter1.writeStartElement("CSRRCFDFY0");
	                xmlWriter1.writeElementString("EACNBR", pReqReceipt.actNum); /* 账号 */
	                xmlWriter1.writeElementString("BEGDAT", tmpDate); /* 开始日期 */
	                xmlWriter1.writeElementString("ENDDAT", tmpDate); /* 结束日期 */
	                xmlWriter1.writeElementString("RRCFLG", printFlag); /* 打印标志（1:未打印，2:已打印） */
	                xmlWriter1.writeElementClosed("BEGAMT"); /* 最小金额 */
	                xmlWriter1.writeElementClosed("ENDAMT"); /* 最大金额 */
	                xmlWriter1.writeElementClosed("RRCCOD"); /* 回单代码 */
	                xmlWriter1.writeEndElement();
	                xmlWriter1.writeEndDocument();

	                String[] tmpStrRet1 = sendToBank(xmlWriter1.toXmlString());
	                int addCount = 0;//新增记录数
	                if (tmpStrRet1[0].length() == 0) {
	                    StringBuilder tmpSbMsg = new StringBuilder();
	                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet1[1], tmpSbMsg);
	                    if (tmpBkReader != null) {
	                        String tmpRetCode = tmpBkReader.getFirstText("/CMBSDKPGK/INFO/RETCOD");
	                        String tmpERRMSG = tmpBkReader.getFirstText("/CMBSDKPGK/INFO/ERRMSG");
	                        if ("0".equals(tmpRetCode)) {
	                            ExecResponse resp = saveReceiptData(tmpBkReader, pReqReceipt, pOneDay);
	                            addCount = resp.rdCount;
	                            WriteBankLogLn(resp.logMsg);
	                        } else {
	                            WriteBankLogLn(tmpRetCode + "-" + tmpERRMSG);
	                        }
	                    } else {
	                        WriteBankLogLn(tmpSbMsg);
	                    }
	                } else {
	                    WriteBankLogLn(tmpStrRet1[0] + "-" + tmpStrRet1[1]);
	                }
	                if (addCount == 0) {
	                	WriteBankLogLn("本次新增记录数为0，不提交回单文件下载请求");
	                    continue;
	                }
				}else{
					WriteBankLogLn("当前配置不执行第一步回单数据查询");
					DownFileRecord downFr = dfHelper.loadFromDbByFilePath(fileKey, qryDate, pReqReceipt.actNum, bankFront.bankCode);
					if(downFr != null && StringHelper.hasAnyChar(downFr.downState)){
						WriteBankLogLn("今天已经发起过回单文件"+fileKey+"的下载，本次不再提交请求");
	                    continue;
					}
				}
				
                WriteBankLogLn("执行" + tmpDate + ("1".equals(printFlag) ? "未打印" : "已打印") + "的回单文件下载");
                CMB01Header bnkHeader2 = new CMB01Header();
                bnkHeader2.FUNNAM = "SDKCSFDFBRTIMG";

                XmlTextWriter xmlWriter2 = new XmlTextWriter();
                xmlWriter2.autoFormat = false;
                writeCommonHeader(xmlWriter2, bnkHeader2);

                xmlWriter2.writeStartElement("CSRRCFDFY0");
                xmlWriter2.writeElementString("EACNBR", pReqReceipt.actNum); /* 账号 */
                xmlWriter2.writeElementString("BEGDAT", "" + tmpDate); /* 开始日期 */
                xmlWriter2.writeElementString("ENDDAT", "" + tmpDate); /* 结束日期 */


                xmlWriter2.writeElementString("RRCFLG", printFlag); /* 打印标志 */
                xmlWriter2.writeElementClosed("BEGAMT"); /* 最小金额 */
                xmlWriter2.writeElementClosed("ENDAMT"); /* 最大金额 */
                xmlWriter2.writeElementClosed("RRCCOD"); /* 回单代码 */
                xmlWriter2.writeEndElement();
                xmlWriter2.writeEndDocument();

                String[] tmpStrRet2 = sendToBank(xmlWriter2.toXmlString());
                if (tmpStrRet2[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet2[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/CMBSDKPGK/INFO/RETCOD");
                        if ("0".equals(tmpRetCode)) {
                        	WriteBankLogLn("回单下载请求提交完成");
                        	execDownAsap = true;
                        	
                        	DownFileRecord downRd = new DownFileRecord();
	                        downRd.srcSys = this.bankFront.bankCode;
	                        downRd.bank = "104";
	                        downRd.bankFrontCode = this.bankFront.code;
	                        downRd.busDate = qryDate;
	                        downRd.downState = "1";
	                        downRd.filePath = fileKey;
	                        downRd.ownAct = pReqReceipt.actNum;
	                        
	                        int rowsAff = dfHelper.insertIfNotExist(downRd);
	                        String aLog = "写入文件下载记录表行数："+rowsAff;
	                        if(rowsAff == 1){
	                        	aLog += "，记录写入成功";
	                        }else if(rowsAff == 0){
	                        	aLog += "，记录已存在";
	                        }
	                        WriteBankLogLn(aLog);
                        	
                        } else {
                            WriteBankLogLn(tmpBkReader.getFirstText("/CMBSDKPGK/INFO/ERRMSG"));
                        }
                    } else {
                    	WriteBankLogLn("查询失败："+tmpSbMsg.toString());
                    }
                } else {
                	WriteBankLogLn("查询失败："+tmpStrRet2[0] + tmpStrRet2[1]);
                }
			} catch (Exception ex) {
                WriteBankLogLn(ex);
            }
		}
		
		if(dfHelper!=null){
    		dfHelper.close();
    	}
		
		if(execDownAsap){
			BOC01TaskReceiptPro.resetDelayCounter();//任务尽快重新获取文件
		}
		return null;
	}
	
	/**将银行返回的数据保存至本地数据库
	 * @throws Exception */
	private ExecResponse saveReceiptData(XmlTextReader pXmlReader, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception{
		ExecResponse resp = new ExecResponse();
		
		//("TRSSEQ");//对应历史明细REFNBR--首选回单编号
		//("NARTX1");//对应历史明细YURREF
		//("BUSNBR");//对应历史明细NAREXT //BTHNBR对应历史明细NAREXT
		//最后一个是CHKCOD，回单验证码，不纳入回单业务参考号
		String[] columnList = new String[]{"TRSSEQ", "NARTX1", "BUSNBR", "BTHNBR", "TRXSET", "SEQNBR", "TRSNBR", "TSKNBR", "TRXNBR", "CHKCOD"};
		
		//key是打印实例号
		HashMap<String, String[]> mapRcpNoRef = new HashMap<String, String[]>();
		//招行同一个打印实例号会有两个节点，第一个节点内容丰富，第个节点有关键回单关联号TRSSEQ
		//先遍历第一遍，取得各个关联用的键值对
		while (pXmlReader.readByParentPath("/CMBSDKPGK")) {
			XElement eachXe = pXmlReader.readedXElement;
			String bkISTNBR = StringHelper.getFirstNotEmpty(eachXe.getSingleText("ISTNBR"), eachXe.getSingleText("PRTINS"));//打印实例号
            if (StringHelper.hasAnyChar(bkISTNBR)) {//只要有打印实例号
            	if(!mapRcpNoRef.containsKey(bkISTNBR)){
            		mapRcpNoRef.put(bkISTNBR, new String[columnList.length]);
            	}
            	String[] refList = mapRcpNoRef.get(bkISTNBR);
            	for(int idx=0; idx<refList.length; idx++){
            		String eachVal = eachXe.getSingleText(columnList[idx]);
            		if(StringHelper.hasAnyChar(eachVal)){
            			refList[idx] = eachVal;
            		}
            	}
            }
		}
		pXmlReader.backToTop();
		ReceiptDataHelper receiptHelper = null;//回单数据保存类，分区分表
		try{
        	receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);
        	int addCount = 0;
        	int execSqlZeroCount = 0;//执行了多少次影响行数为0的sql写入操作
        	int totalCount = mapRcpNoRef.size();
        	int existCount = receiptHelper.getTotalCountByAct(pReqReceipt.actNum, pOneDay);
        	long totalSpanDbMilSecs = 0;//数据库操作总耗时
        	//遍历第二次，进行写入回单数据
    		while (pXmlReader.readByParentPath("/CMBSDKPGK")) {
    			XElement eachXe = pXmlReader.readedXElement;
                String bkISTNBR = StringHelper.getFirstNotEmpty(eachXe.getSingleText("ISTNBR"), eachXe.getSingleText("PRTINS"));//打印实例号
                if (StringHelper.hasAnyChar(bkISTNBR)) {//只要有打印实例号
                	if(!mapRcpNoRef.containsKey(bkISTNBR)){
                		resp.logMsg = "读取银行返回数据出错：未读取的ISTNBR/PRTINS："+bkISTNBR;
                		this.WriteBankLogAndLimit(resp.logMsg);
                		return resp;
                	}
                	String[] refList = mapRcpNoRef.get(bkISTNBR);
                	//最后一个是CHKCOD
                    ReceiptData eachData = new ReceiptData();
                    eachData.chkCode = refList[refList.length-1];
                    refList[refList.length-1] = "";//CHKCOD置空，不纳入回单业务参考号
                    eachData.istNbr = bkISTNBR;
                    //去空去重
                    String[] seqList = StringHelper.filterOutRepetitionAndEmpty(refList);
                    if(seqList.length>0){
                    	eachData.receiptNo = seqList[0];
                    }
                    if(seqList.length>1){
                    	eachData.busRef = seqList[1];
                    }
                    if(seqList.length>2){
                		eachData.busRef2 = seqList[2];
                	}
                	if(seqList.length>3){
                		eachData.busRef3 = seqList[3];
                	}
                	if(StringHelper.isNullOrEmpty(eachData.receiptNo)){
                		this.WriteBankLogLn("打印示例号为"+eachData.istNbr+"的记录，提取不到receiptNo");
                		eachData.receiptNo = eachData.istNbr;
                	}
                    eachData.srcSys = "CMB01";
                    eachData.bank = "308";
                    String eachAmt = "";
                    String[] amtColumns = new String[]{"TRSAMT", "INTAMT", "TRXAMT", "AMTTRS", "ACTAMT", "BILAMT", "OPNAMT", "TRXAM1", "FEEAMT"};
                    for (int i = 0; i < amtColumns.length; i++) {
                        eachAmt = eachXe.getSingleTextNotNull(amtColumns[i]);
                        if (StringHelper.hasAnyChar(eachAmt)) {
                            break;
                        }
                    }
                    if (StringHelper.isNullOrEmpty(eachAmt) && "SAINTLSBZ0".equals(eachXe.name)) {
                        //利息金额
                        eachAmt = eachXe.getSingleTextNotNull("INTRST");
                    } else if (StringHelper.isNullOrEmpty(eachAmt) && "EXICORRBZ1".equals(eachXe.name)) {
                        //结汇
                        String[] amts = new String[]{"OUTAMT", "RCVAMT"};//OUTAMT卖出金额，RCVAMT买入金额
                        for (int i = 0; i < amts.length; i++) {
                            String outRcvAmt = eachXe.getSingleTextNotNull(amts[i]);
                            if (StringHelper.hasAnyChar(outRcvAmt)) {
                                BigDecimal decAmtOutRcv = new BigDecimal(outRcvAmt);
                                BigDecimal decZero = new BigDecimal("0.00");
                                if (decAmtOutRcv.compareTo(decZero) != 0) {
                                    eachAmt = outRcvAmt;
                                    break;
                                }
                            }
                        }
                    }
                    if(StringHelper.hasAnyChar(eachAmt)){
                    	eachData.amount = new BigDecimal(eachAmt);
                    }
                    eachData.ownAct = pReqReceipt.actNum;
                    eachData.cur = pReqReceipt.actCur;
                    eachData.setBusDate(pOneDay);
                    //CPRRCRTNX1 对公转账退票回单（批量）；CPRRCRCVX1收款
                    if ("CPRRCRTNX1".equals(eachXe.name) || "CPRRCRCVX1".equals(eachXe.name)) {
                    	eachData.moneyWay = "2";
                    } else if ("CSTRFPRTX0".equals(eachXe.name) || "AGNCBPAYZ1".equals(eachXe.name) || "CPRRCSNDX1".equals(eachXe.name)) {
                    	eachData.moneyWay = "1";//付款
                    }
                  //增加对方户名
                    String[] oppActNames = new String[]{"RCVEAN", "RCVNAM", "BNFNAM", "ECLNAM", "TRXNM1"};
                    for (int i = 0; i < oppActNames.length; i++) {
                        String oppActName = eachXe.getSingleTextNotNull(oppActNames[i]);
                        if (StringHelper.hasAnyChar(oppActName)) {
                        	eachData.oppActName=oppActName;
                            break;
                        }
                    }
                  //增加对方账号
                    String[] oppActNums = new String[]{"RCVEAC", "BNFACC", "INSEAC","RCVACC", "EBKACC"};
                    for (int i = 0; i < oppActNums.length; i++) {
                        String oppActNum = eachXe.getSingleTextNotNull(oppActNums[i]);
                        if (StringHelper.hasAnyChar(oppActNum)) {
                        	eachData.oppActNum=oppActNum;
                            break;
                        }
                    }
                    eachData.summary = eachXe.getSingleTextNotNull("TRXRMK");
                    
                    try{
                    	Date beginTime = new Date();
                    	int inRe = receiptHelper.insertIfNotExist(eachData, true);
                    	totalSpanDbMilSecs += DateHelper.getDifferMilSecs(new Date(), beginTime);
                        if(inRe>0){
                        	addCount++;
                        }else if(inRe==0){
                        	execSqlZeroCount++;
                        }else{
                        	WriteBankLogLn(eachData.receiptNo+"写入数据库，影响行数："+inRe);
                        }
                        int totalDealCount = addCount+execSqlZeroCount;
                        if(totalDealCount % 100 == 0){
                        	WriteBankLogLn("处理"+totalDealCount+"笔，其中数据库操作耗时"+totalSpanDbMilSecs+"毫秒");
                        }
                    }catch(Exception ex){
                    	XmlTextWriter xmlForLog = new XmlTextWriter();
                    	xmlForLog.writeXElement(eachXe);
                    	WriteBankLogLn(ex, eachData.istNbr, xmlForLog.toXmlString());
                    }
                } else if (!"INFO".equals(eachXe.name) && !"CSRRCFDFZ1".equals(eachXe.name) && !"NPTRFRVIX1".equals(eachXe.name)) {
                    FGBiz.logTrace.infoNoTimeBank(reqHeader.bankCode, reqHeader.transType, "节点" + eachXe.name + "无打印实例号<ISTNBR>");
                }
            }
        	resp.rdCount = addCount;
        	if(addCount > 0 || execSqlZeroCount > 0){
        		resp.isSucceed = true;
        	}
        	double spanSecs = totalSpanDbMilSecs/1000;
        	resp.logMsg = "总"+totalCount+"个回单打印实例号，已存在"+existCount+"条，本次新增"+addCount+"条，其中数据库操作总耗时"+Format.DecimalAmtFormat.format(spanSecs)+"秒";
        	FGBiz.logTrace.info(getLogCode(), resp.logMsg);
		}catch(Exception ex){
			resp.logMsg = LogHelper.getStackTrace(ex);
			FGBiz.logTrace.exception(getLogCode(), ex);
        }finally{
        	if(receiptHelper!=null){
        		receiptHelper.close();
        	}
        }
		
		return resp;
	}

}
